#include "UtilityPCH.h"

#include "UT_SpectrumRGB.h"
#include "UT_SpectrumHelper.h"
#include "UT_TArray.h"

#include "UT_SpectrumSampleData.c"

using namespace Utility;
//---------------------------------------------------------------------
UT_SpectrumRGB::UT_SpectrumRGB(float v /* = 0.f */)
	: UT_SpectrumBase<3>(v) 
{
}
//---------------------------------------------------------------------
UT_SpectrumRGB::UT_SpectrumRGB(const UT_SpectrumBase<3> &v)
	: UT_SpectrumBase<3>(v) 
{
}
//---------------------------------------------------------------------
UT_SpectrumRGB::UT_SpectrumRGB(const UT_SpectrumRGB &s, SpectrumType type /* = SPECTRUM_REFLECTANCE */)
{
	*this = s;
}
//---------------------------------------------------------------------
UT_SpectrumRGB UT_SpectrumRGB::FromRGB(const float rgb[3], SpectrumType type /* = SPECTRUM_REFLECTANCE */)
{
	UT_SpectrumRGB s;
	s.c[0] = rgb[0];
	s.c[1] = rgb[1];
	s.c[2] = rgb[2];
	UT_ASSERT(!s.HasNaNs());
	return s;
}
//---------------------------------------------------------------------
const UT_SpectrumRGB& UT_SpectrumRGB::ToRGBSpectrum() const
{
	return *this;
}
//---------------------------------------------------------------------
void UT_SpectrumRGB::ToRGB(float *rgb) const
{
	rgb[0] = c[0];
	rgb[1] = c[1];
	rgb[2] = c[2];
}
//---------------------------------------------------------------------
void UT_SpectrumRGB::ToXYZ(float xyz[3]) const
{
	UT_SpectrumHelper::RGBToXYZ(c, xyz);
}
//---------------------------------------------------------------------
UT_SpectrumRGB UT_SpectrumRGB::FromXYZ(const float xyz[3], SpectrumType type /* = SPECTRUM_REFLECTANCE */)
{
	UT_SpectrumRGB r;
	UT_SpectrumHelper::XYZToRGB(xyz, r.c);
	return r;
}
//---------------------------------------------------------------------
float UT_SpectrumRGB::y() const
{
	const float YWeight[3] = { 0.212671f, 0.715160f, 0.072169f };
	return YWeight[0] * c[0] + YWeight[1] * c[1] + YWeight[2] * c[2];
}
//---------------------------------------------------------------------
UT_SpectrumRGB UT_SpectrumRGB::CreateSpectrumFromSamples(const float *lambda, const float *v, int n)
{
	// Sort samples if unordered, use sorted for returned spectrum
	if (!UT_SpectrumHelper::SpectrumSamplesSorted(lambda, v, n))
	{
		UT_TVector<float> slambda(&lambda[0], &lambda[n]);
		UT_TVector<float> sv(&v[0], &v[n]);
		UT_SpectrumHelper::SortSpectrumSamples(&slambda.GetAt(0), &sv.GetAt(0), n);

		return CreateSpectrumFromSamples(&slambda.GetAt(0), &sv.GetAt(0), n);
	}
	float xyz[3] = { 0, 0, 0 };
	float yint = 0.f;
	for (int i = 0; i < siCIESampleCount; ++i) 
	{
		yint += CIE_Y[i];
		float val = UT_SpectrumHelper::InterpolateSpectrumSamples(lambda, v, n, CIE_lambda[i]);
		xyz[0] += val * CIE_X[i];
		xyz[1] += val * CIE_Y[i];
		xyz[2] += val * CIE_Z[i];
	}
	xyz[0] /= yint;
	xyz[1] /= yint;
	xyz[2] /= yint;
	return FromXYZ(xyz);
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------